package edos.prm.role;

import java.util.HashSet;
import edos.prm.activity.Operation;
import edos.prm.artifact.Artifact;

/**
 * A {@code Right} represents a privilege to execute an {@code Operation} or
 * a series of operations on an {@code Activity}.
 * 
 * @version 1.0
 */
public final class Right implements Artifact {
	
	private HashSet<Operation> operationSet;

	/**
	 * The {@code AllRights} right value permits the execution of all activity
	 * operations.
	 * <p>
	 * This right is assigned to the bootstrap process. Obviously, this right
	 * should be accorded with extreme caution.
	 */
	public final static Right AllRights = new Right();
	
	private Right() {
		operationSet = new HashSet<Operation>();
	}
	
	/**
	 * Create a Right object for a series of activity operations
	 * 
	 * @param operations the operations controlled by this right.
	 */
	public Right(Operation...operations) {
		operationSet = new HashSet<Operation>();
		for ( Operation op : operations )
			this.operationSet.add(op);
	}

	/**
	 * Return the activity operations associated with this right
	 * 
	 * @return an array of operations permitted by this right
	 */
	public Operation[] getOperations() {
		Operation[] result = new Operation[this.operationSet.size()];
		this.operationSet.toArray(result);
		return result;
	}
	
	/**
	 * Determine if this right permits the operations of the argument right.
	 * 
	 * @param right an arbitrary right.
	 * @return true if all operations of right are also permitted by this right.
	 */
	public boolean implies(Right right) {
		return this.operationSet.containsAll(right.operationSet);
	}
	
	/*
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer("[");
		for ( Operation op : operationSet )
			sb.append(op.getName() + " ");
		sb.append("]");
		return sb.toString();
	}
	
	/*
	 * @see java.lang.Object#equals()
	 */
	public boolean equals(Object obj) {
		if ( obj instanceof Right ) {
			Right right = (Right)obj;
			if ( right.operationSet.size() == this.operationSet.size() ) {
				for ( Operation op : this.operationSet )
					if ( !right.operationSet.contains(op) )
						return false;
				return true;
			}
			return false;
		}
		return false;
	}
	
	/*
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode () {
		int value = 0;
		for ( Operation op : this.operationSet )
			value += op.hashCode();
		return value;
	}
}
